package com.hmy.finance.service.core.dto;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hmy.finance.api.bo.core.request.ClaimGenerateRequest;
import com.hmy.finance.api.bo.core.request.enums.ClaimBillTypeEnum;
import com.hmy.finance.api.bo.core.request.enums.FeeTypeEnum;
import com.hmy.finance.api.bo.core.request.enums.ProfitLossTypeEnum;
import com.hmy.finance.api.bo.core.response.BaseGenerateProfitLossResponse;
import com.hmy.finance.common.enums.BusinessBillTypeEnum;
import com.hmy.finance.common.enums.ProfitLossStatusEnum;
import com.hmy.finance.dal.po.DeviceProfitLossDetailPo;
import com.hmy.finance.dal.po.DeviceRentalRecordPo;
import com.hmy.finance.dal.po.ProfitLossRecordPo;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 索赔生成损益业务记录业务逻辑处理参数
 *
 * @author songkf
 */
@Data
public class ClaimGenerateDto implements Serializable {
    private static final long serialVersionUID = 3284095386780681456L;
    /**
     * 损益类型
     */
    private final ProfitLossTypeEnum profitLossType = ProfitLossTypeEnum.LOSS;
    /**
     * 客户ID
     */
    private Long customerId;
    /**
     * 合同ID
     */
    private Long contractId;
    /**
     * 进场单ID
     */
    private Long entryFormId;
    /**
     * 业务单据ID
     */
    private Long businessBillId;
    /**
     * 索赔单关联单据类型
     */
    private ClaimBillTypeEnum claimRelatedBillType;
    /**
     * 索赔单关联单据ID
     */
    private Long claimRelatedBillId;
    /**
     * 索赔设备ID
     */
    private Long claimDeviceId;
    /**
     * 索赔金额
     */
    private BigDecimal claimAmount;
    /**
     * 是否需要更新设备租赁记录
     */
    private Boolean needUpdateDeviceRentalRecord = Boolean.FALSE;
    /**
     * 设备租赁记录
     */
    private DeviceRentalRecordPo deviceRentalRecordPo;
    /**
     * 待处理的损益业务记录集合
     */
    private List<ProfitLossRecordPo> profitLossRecordPoList = new ArrayList<>(1);

    private List<DeviceProfitLossDetailPo> deviceProfitLossDetailPoList = new ArrayList<>(1);

    /**
     * 组装索赔生成损益业务记录业务逻辑处理参数
     *
     * @param request 索赔生成请求
     * @return 索赔生成损益业务记录业务逻辑处理参数
     * @author songkf
     */
    public static ClaimGenerateDto buildClaimGenerateDto(ClaimGenerateRequest request) {
        ClaimGenerateDto dto = new ClaimGenerateDto();
        dto.setClaimRelatedBillType(request.getClaimRelatedBillType());
        dto.setClaimRelatedBillId(request.getClaimRelatedBillId());
        dto.setClaimDeviceId(request.getClaimDeviceId());
        dto.setClaimAmount(request.getClaimAmount());
        dto.setBusinessBillId(request.getBusinessBillId());
        dto.setEntryFormId(request.getEntryFormId());
        dto.setCustomerId(request.getCustomerId());
        dto.setContractId(request.getContractId());
        return dto;
    }

    public void assembleProfitLossRecord(DefaultIdentifierGenerator identifierGenerator) {
        if (this.getDeviceRentalRecordPo() != null) {
            ProfitLossRecordPo profitLossRecordPo = new ProfitLossRecordPo();
            profitLossRecordPo.setCustomerId(this.getDeviceRentalRecordPo().getCustomerId());
            profitLossRecordPo.setContractId(this.getDeviceRentalRecordPo().getContractId());
            profitLossRecordPo.setBusinessBillId(this.getBusinessBillId());
            profitLossRecordPo.setBusinessBillType(BusinessBillTypeEnum.CLAIMS);
            profitLossRecordPo.setFeeType(FeeTypeEnum.CLAIMS_FEE);
            profitLossRecordPo.setTotalFeeAmount(this.getClaimAmount());
            profitLossRecordPo.setStatus(ProfitLossStatusEnum.ALREADY_EFFECTIVE);
            profitLossRecordPo.setFeeIncurredTime(LocalDateTime.now());
            profitLossRecordPo.setId(identifierGenerator.nextId(profitLossRecordPo));
            this.getProfitLossRecordPoList().add(profitLossRecordPo);
            this.assembleDeviceProfitLossDetail(identifierGenerator, profitLossRecordPo.getId(), this.getClaimAmount(), FeeTypeEnum.CLAIMS_FEE);
        }
    }

    private void assembleDeviceProfitLossDetail(DefaultIdentifierGenerator identifierGenerator, Long id, BigDecimal claimAmount, FeeTypeEnum feeTypeEnum) {
        DeviceProfitLossDetailPo deviceProfitLossDetailPo = new DeviceProfitLossDetailPo();
        deviceProfitLossDetailPo.setProfitLossRecordId(id);
        deviceProfitLossDetailPo.setDeviceId(this.getClaimDeviceId());
        deviceProfitLossDetailPo.setDeviceNo(this.getDeviceRentalRecordPo().getDeviceExtensionInfo().getDeviceNo());
        deviceProfitLossDetailPo.setContractId(this.getDeviceRentalRecordPo().getContractId());
        deviceProfitLossDetailPo.setContractNo(deviceRentalRecordPo.getContractNo());
        deviceProfitLossDetailPo.setFee(claimAmount);
        deviceProfitLossDetailPo.setFeeType(feeTypeEnum);
        deviceProfitLossDetailPo.setBusinessBillType(BusinessBillTypeEnum.CLAIMS);
        deviceProfitLossDetailPo.setDeviceRentalRecordId(this.getDeviceRentalRecordPo().getId());
        deviceProfitLossDetailPo.setFeeIncurredTime(LocalDateTime.now());
        deviceProfitLossDetailPo.setId(identifierGenerator.nextId(deviceProfitLossDetailPo));
        if (deviceRentalRecordPo.getExpenseCycleEndTime() != null && deviceRentalRecordPo.getExpenseCycleEndTime().isBefore(LocalDateTime.now())) {
            deviceRentalRecordPo.setExpenseCycleEndTime(LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX));
            this.setNeedUpdateDeviceRentalRecord(Boolean.TRUE);
        }
        this.getDeviceProfitLossDetailPoList().add(deviceProfitLossDetailPo);
    }

    /**
     * 构建设备租赁记录查询条件
     *
     * @return 设备租赁记录查询条件
     * @author songkf
     */
    public LambdaQueryWrapper<DeviceRentalRecordPo> buildDeviceRentalRecordPoLambdaQueryWrapper() {
        LambdaQueryWrapper<DeviceRentalRecordPo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(DeviceRentalRecordPo::getCustomerId, this.getCustomerId());
        lambdaQueryWrapper.eq(DeviceRentalRecordPo::getContractId, this.getContractId());
        lambdaQueryWrapper.eq(DeviceRentalRecordPo::getDeviceId, this.getClaimDeviceId());
        lambdaQueryWrapper.eq(DeviceRentalRecordPo::getEntryFormId, this.getEntryFormId());
        return lambdaQueryWrapper;
    }

    public BaseGenerateProfitLossResponse getResponse() {
        BaseGenerateProfitLossResponse response = new BaseGenerateProfitLossResponse();
        response.setResult(Boolean.TRUE);
        return response;
    }

    public Wrapper<DeviceRentalRecordPo> getCheckRentalStatusWrapper() {
        return Wrappers.lambdaQuery(DeviceRentalRecordPo.class)
                .eq(DeviceRentalRecordPo::getDeviceId, this.getClaimDeviceId())
//                .isNull(DeviceRentalRecordPo::getRentalEndTime)
                ;
    }
}
